/*
 * Copyright (C) 2010 ExtPlus.org
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.extplus.ajax;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import org.extplus.base.Response;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

/**
 * 抽象AJAX任务请求管理类
 * <p>
 * 实现了请求数据的解析，将每个请求消息实体分发给每个URI处理，最后将处理完返回的响应消息重新组装，返回给客户端。
 * </p>
 */
public abstract class AbstractAjaxTask<T> implements AjaxTask<T, String> {
	private String data;

	private OriginalAjaxTaskRequest[] orgRequests;

	private List<AjaxTaskRequest<T>> requests = new ArrayList<AjaxTaskRequest<T>>();

	private List<AjaxTaskResponse> responses = new ArrayList<AjaxTaskResponse>();

	private Response<List<AjaxTaskResponse>> response = new Response<List<AjaxTaskResponse>>();

	/**
	 * 请求参数解析，将String类型的参数解析成请求参数实体
	 * @param uri URI
	 * @param params 请求参数
	 * @return 请求参数实体
	 */
	public abstract T parseParams(String uri, String params);

	/**
	 * 处理AJAX请求，根据URI处理每个请求实体，返回响应消息实体
	 * @param uri URI
	 * @param obj 请求参数实体
	 * @return 响应消息实体
	 */
	public abstract Response<String> processRequest(String uri, T obj);

	/**
	 * 处理请求数据，返回响应数据实体
	 * @param data 请求数据
	 * @param returnObj 是否返回对象类型响应数据
	 * @return 响应数据对象
	 */
	public Response<List<AjaxTaskResponse>> process(String data, boolean returnObj) {
		this.data = data;
		this.parseData();
		this.parseRequest();
		this.processResponse();
		return this.response;
	}

	/**
	 * 处理请求数据，返回响应数据实体
	 * @param data 请求数据
	 * @return 响应数据
	 */
	public String process(String data) {
		this.process(data, true);
		return this.parseResponse(this.response);
	}

	private void parseData() {
		Gson gson = new Gson();
		Type type = new TypeToken<OriginalAjaxTaskRequest[]>() {
		}.getType();
		this.orgRequests = gson.fromJson(this.data, type);
	}

	private void parseRequest() {
		AjaxTaskRequest<T> req;
		for (OriginalAjaxTaskRequest orgReq : orgRequests) {
			req = new AjaxTaskRequest<T>();
			req.setUri(orgReq.getUri());
			req.setParams(this.convertJson(orgReq.getParams()));
			req.setParamsObj(this.parseParams(req.getUri(), req.getParams()));
			this.requests.add(req);
		}
	}

	private void processResponse() {
		Response<String> resp;
		AjaxTaskResponse taskResp;
		for (AjaxTaskRequest<T> req : this.requests) {
			resp = this.processRequest(req.getUri(), req.getParamsObj());
			if (resp != null) {
				taskResp = new AjaxTaskResponse();
				taskResp.setUri(req.getUri());
				taskResp.setSuccess(resp.isSuccess());
				taskResp.setMessage(resp.getMessage());
				taskResp.setData(resp.getData());
				this.responses.add(taskResp);
			}
		}
		this.response.setSuccess(true);
		this.response.setMessage("success");
		this.response.setData(this.responses);
	}

	public String parseResponse(Response<List<AjaxTaskResponse>> response) {
		Gson gson = new Gson();
		Type type = new TypeToken<Response<List<AjaxTaskResponse>>>() {
		}.getType();
		return gson.toJson(response, type);
	}

	private String convertJson(String str) {
		if (str.length() == 0) {
			return "";
		}

		String ret = "{";
		String[] arr = str.split("&");
		for (String s : arr) {
			int i;
			if ((i = s.indexOf("=")) != -1) {
				if (ret.length() > 1) {
					ret += ",";
				}
				ret += "\"" + s.substring(0, i) + "\":\"" + s.substring(i + 1) + "\"";
			}
		}
		return (ret + "}");
	}
}
